#ifndef _YM2612_STATE_DATA_
#define _YM2612_STATE_DATA_
//=======================================================================================================
// YM2612StateData
// Author: Landon Podbielski
// Description: This file is a collection of structures used to simplify the representation of the current
//				state of a YM2612. YM2612StateData, found at the bottom of this file, represents all the
//				information you need to save the state of the chip.
//-------------------------------------------------------------------------------------------------------

#include <map>
#include <vector>
#include "YM2612Enum.h"
#include "YM2612Value.h"

//-------------------------------------------------------------------------------------------------------
//YM2612Instrument - Wraps all data related to an instrument section
//-------------------------------------------------------------------------------------------------------
struct YM2612Instrument : public YM2612Values
{
	YM2612Instrument()
		:CH01_EN( INS_CHAN01_EN, 0, 1, 0 )
		,CH02_EN( INS_CHAN02_EN, 0, 1, 0 )
		,CH03_EN( INS_CHAN03_EN, 0, 1, 0 )
		,CH04_EN( INS_CHAN04_EN, 0, 1, 0 )
		,CH05_EN( INS_CHAN05_EN, 0, 1, 0 )
		,CH06_EN( INS_CHAN06_EN, 0, 1, 0 )
	{
	}
	virtual int NumParams() { return 6; }

	YM2612Value CH01_EN;
	YM2612Value CH02_EN;
	YM2612Value CH03_EN;
	YM2612Value CH04_EN;
	YM2612Value CH05_EN;
	YM2612Value CH06_EN;
};

//-------------------------------------------------------------------------------------------------------
//YM2612Operator - Wraps all data related to a YM2612 channel operator
//-------------------------------------------------------------------------------------------------------
struct YM2612Operator : public YM2612Values
{
	YM2612Operator()
		:P_DT( DT, 0, 7 )
		,P_MUL( MUL, 0, 15 )
		,P_TL( TL, 0, 127 )
		,P_RS( RS, 0, 3 )
		,P_AR( AR, 0, 31 )
		,P_DR1( DR1, 0, 31 )
		,P_DR2( DR2, 0, 31 )
		,P_AM( AM, 0, 1 )
		,P_DL1( DL1, 0, 15 )
		,P_RR( RR, 0, 15 )
		,P_F1( F1, 0, 254 )
		,P_F2( F2, 0, 254 )
	{
	}
	virtual int NumParams() { return 12; }

	YM2612Value P_DT;
	YM2612Value P_MUL;
	YM2612Value P_TL;
	YM2612Value P_RS;
	YM2612Value P_AR;
	YM2612Value P_DR1;
	YM2612Value P_DR2;
	YM2612Value P_AM;
	YM2612Value P_DL1;
	YM2612Value P_RR;
	YM2612Value P_F1;
	YM2612Value P_F2;
};

//-------------------------------------------------------------------------------------------------------
//YM2612Algorithm - Wraps a YM2612 algorithm selection
//-------------------------------------------------------------------------------------------------------
struct YM2612Algorithm : public YM2612Values
{
	YM2612Algorithm()
		:Alg01( ALG01, 0, 1, 0 )
		,Alg02( ALG02, 0, 1, 0 )
		,Alg03( ALG03, 0, 1, 0 )
		,Alg04( ALG04, 0, 1, 0 )
		,Alg05( ALG05, 0, 1, 0 )
		,Alg06( ALG06, 0, 1, 0 )
		,Alg07( ALG07, 0, 1, 0 )
		,Alg08( ALG08, 0, 1, 0 )
	{
	}
	virtual int NumParams() { return 8; }

	int GetAlgSelection() 
	{
		for( int i = 0; i < NumParams(); i++ )
		{
			YM2612Value* val = CastValueData(i);
			if( val->GetValueAsFloat() > 0.01f )
				return i;
		}
		return 0;
	}

	YM2612Value Alg01;
	YM2612Value Alg02;
	YM2612Value Alg03;
	YM2612Value Alg04;
	YM2612Value Alg05;
	YM2612Value Alg06;
	YM2612Value Alg07;
	YM2612Value Alg08;
};

//-------------------------------------------------------------------------------------------------------
//YM2612ChannelData - Wraps global data for each channel
//-------------------------------------------------------------------------------------------------------
struct YM2612ChannelData : public YM2612Values
{
	YM2612ChannelData()
		:Feedback( ALG_FEEDBACK, 0, 7, 0 )
		,P_LFO_EN( LFO_EN, 0, 1, 0 )
		,P_LFO( LFO, 0, 7, 0 )
	{
	}
	virtual int NumParams() { return 1; }

	YM2612Value Feedback;
	YM2612Value P_LFO_EN;
	YM2612Value P_LFO;
	//YM2612Value P_AMS;
	//YM2612Value P_FMS;
	//YM2612Value P_PAN;

	YM2612Operator Operators[4];
	YM2612Algorithm Algorithm;
	
};

//-------------------------------------------------------------------------------------------------------
//YM2612StateData - Initializes and keeps track of all the data representing
//					the state of a YM2612 at any given time.
//-------------------------------------------------------------------------------------------------------
struct YM2612StateData
{
	YM2612StateData();
	
	//Getters
	int GetParmOpIndex( int channel, YM2612Param parm, int op );
	YM2612Value* GetValueByIndex( int index );
	YM2612Value* GetMidiLearn();
	void GetMidiHookups(int hook, std::vector<YM2612Value*>& out) const;
	int GetSelectedInstrument() const;
	
	static int GetNumParms();

	//Member variables
	YM2612Value StateProps[14];
	YM2612Instrument Instruments[6];
	YM2612ChannelData Channels[6];
	int MinParmIndex;
	int MaxParmIndex;
	int MinAlgIndex;
	int MaxAlgIndex;
	int MinStatePropsIndex;
	int MinStatePropsInsSelIndex;
	int MaxStatePropsInsSelIndex;
	int MaxStatePropsIndex;
	int MaxIndex;
	std::map<YM2612Value*, bool> MidiControls;
	std::map<int, YM2612Value*> IndexMap;
};

#endif _YM2612_STATE_DATA_